#include "book.h"
#include "tcpclient.h"
#include <QInputDialog>
#include <QMessageBox>
#include <QFileDialog>
#include "opewidget.h"
#include "sharefile.h"

Book::Book(QWidget *parent) : QWidget(parent)
{

    m_strEnterDir.clear();
    m_bDownload = false;
    m_pTimer = new QTimer;//创建定时器
    m_pBookListW = new QListWidget;
    m_pReturnPB = new QPushButton("返回");
    m_pCreateDirPB = new QPushButton("创建文件夹");
    m_pDelPB = new QPushButton("删除文件夹");
    m_pRenamePB = new QPushButton("重命名文件");
    m_pFlushPB = new QPushButton("刷新文件");
    QVBoxLayout *pDirVBL = new QVBoxLayout;
    pDirVBL->addWidget(m_pReturnPB);
    pDirVBL->addWidget(m_pCreateDirPB);
    pDirVBL->addWidget(m_pDelPB);
    pDirVBL->addWidget(m_pRenamePB);
    pDirVBL->addWidget(m_pFlushPB);//垂直布局



    m_pUploadPB = new QPushButton("上传文件");
    m_pDownloadPB = new QPushButton("下载文件");
    m_pDelFilePB = new QPushButton("删除文件");
    m_pShareFilePB = new QPushButton("共享文件");
    m_pMoveFilePB = new QPushButton("移动文件");
    m_pSelectDirPB = new QPushButton("目标目录");
    m_pSelectDirPB->setEnabled(false);
    QVBoxLayout *pFileVBL = new QVBoxLayout;
    pFileVBL->addWidget(m_pUploadPB);
    pFileVBL->addWidget(m_pDownloadPB);
    pFileVBL->addWidget(m_pDelFilePB);
    pFileVBL->addWidget(m_pShareFilePB);
    pFileVBL->addWidget(m_pMoveFilePB);
    pFileVBL->addWidget(m_pSelectDirPB);

    QHBoxLayout *pMain = new QHBoxLayout;
    pMain->addWidget(m_pBookListW);
    pMain->addLayout(pDirVBL);
    pMain->addLayout(pFileVBL);

    setLayout(pMain);

    connect(m_pCreateDirPB,SIGNAL(clicked(bool)),this,SLOT(createDir()));
    connect(m_pFlushPB,SIGNAL(clicked(bool)),this,SLOT(flushFile()));
    connect(m_pDelPB,SIGNAL(clicked(bool)),this,SLOT(delDir()));
    connect(m_pRenamePB,SIGNAL(clicked(bool)),this,SLOT(renameFile()));
    connect(m_pBookListW,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(enterDir(QModelIndex)));//发出双击信号，传入modelindex，形参类型保持一致
    connect(m_pReturnPB,SIGNAL(clicked(bool)),this,SLOT(returnPre()));
    connect(m_pUploadPB,SIGNAL(clicked(bool)),this,SLOT(uploadFile()));
    connect(m_pTimer,SIGNAL(timeout()),this,SLOT(uploadFileData()));
    connect(m_pDelFilePB,SIGNAL(clicked(bool)),this,SLOT(delRegFile()));
    connect(m_pDownloadPB,SIGNAL(clicked(bool)),this,SLOT(downloadFile()));
    connect(m_pShareFilePB,SIGNAL(clicked(bool)),this,SLOT(shareFile()));
    connect(m_pMoveFilePB,SIGNAL(clicked(bool)),this,SLOT(moveFile()));
    connect(m_pSelectDirPB,SIGNAL(clicked(bool)),this,SLOT(selectDestDir()));
}

void Book::updateFileList(const PDU *pdu)
{
    if(pdu == nullptr) return;
    //有效就把信息提取出来
    //清除掉重复显示的代码
    QListWidgetItem *pItemTmp = nullptr;
    int row = m_pBookListW->count();
    while(row >0)
    {
        pItemTmp = m_pBookListW->item(row - 1);
        m_pBookListW->removeItemWidget(pItemTmp);
        delete pItemTmp;
        row -=1;
    }
    FileInfo *pFileInfo = nullptr;
    int icount = pdu->uiMsgLen / sizeof(FileInfo);
    for(int i = 0;i< icount ;++i)
    {
        pFileInfo = (FileInfo *)(pdu->caMsg) +i;
        qDebug() << pFileInfo->caFileName  << pFileInfo->iFileType;
        QListWidgetItem *pItem = new QListWidgetItem;
        if(pFileInfo->iFileType == 0)
        {
            pItem->setIcon(QIcon(QPixmap(":/map/icon.jpg")));
        }
        else if(pFileInfo->iFileType == 1)
        {
            pItem->setIcon(QIcon(QPixmap(":/map/file.jpg")));
        }
        pItem->setText(pFileInfo->caFileName);
        m_pBookListW->addItem(pItem);
    }

}

void Book::clearEnterDir()
{
    m_strEnterDir.clear();

}

QString Book::enterDir()
{
    return m_strEnterDir;//单例调用
}

void Book::setDownloadStatus(bool status)
{
    m_bDownload = status;
}

bool Book::getDownloadStatus()
{
    return m_bDownload;
}

QString Book::getSaveFilePath()
{
    return m_strSaveFilePath;
}

QString Book::getShareFileName()
{
    return m_strShareFileName;
}

void Book::createDir()//创建路径
{
    //用户名，目录信息，文件夹名字
    QString strNewDir = QInputDialog::getText(this,"新建文件夹","新文件夹名字");//返回值类型是字符串,this,标题，提示
    if(!strNewDir.isEmpty())
    {
        if(strNewDir.size() > 32)
        {
            QMessageBox::warning(this,"新键文件夹","新文件夹名字不能超过32个字符");
        }
        else
        {
            QString strName = TcpClient::getInstance().loginName();
            QString strCurPath = TcpClient::getInstance().curPath();
            PDU *pdu = mkPDU(strCurPath.size() + 1);
            pdu->uiMsgType= ENUM_MSG_TYPE_CREATE_DIR_REQUEST;
            strncpy(pdu->caData,strName.toStdString().c_str(),strName.size());
            strncpy(pdu->caData + 32,strNewDir.toStdString().c_str(),strNewDir.size());
            memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());

            TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
            free(pdu);
            pdu = nullptr;
        }
    }
    else
    {
        QMessageBox::warning(this,"新建文件夹","新文件夹名字不能为空");
    }
}

void Book::flushFile()//刷新文件也就是显示出文件的内容
{
    //需要发送请求，通过协议内容进行发送
    QString strCurPath = TcpClient::getInstance().curPath();//保存当前所在的路径
    PDU *pdu = mkPDU(strCurPath.size() +1 );
    pdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FILE_REQUEST;
    strncpy((char*)(pdu->caMsg),strCurPath.toStdString().c_str(),strCurPath.size());//把这个当前路径存入pdu
    TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
    free(pdu);
    pdu = nullptr;
}

void Book::returnPre()
{
    //判断当前所在的目录是否是顶层目录
    QString strCurPath = TcpClient::getInstance().curPath();
    QString strRootPath ="./" + TcpClient::getInstance().loginName();//登录的用户名,最顶层目录
    if(strCurPath == strRootPath)//目录和自己的顶层路径是否相同，相同的话就无法进行返回了
    {
        QMessageBox::warning(this,"返回","返回失败：已经在最开始的文件夹目录中");
    }
    else//"./aa/bb//cc/ 找斜杠
    {
        int index = strCurPath.lastIndexOf('/');//从后往前找斜杠
        strCurPath.remove(index,strCurPath.size() - index);
        qDebug() << "return -->"<<strCurPath;
        TcpClient::getInstance().setCurPath(strCurPath);

        clearEnterDir();
        flushFile();//返回上一层的信息，直接调用刷新功能，也可以再重写一遍刷新上的代码，一样
    }

}



void Book::delDir()
{
    //需要获取当前保存的目录
    QString strCurPath = TcpClient::getInstance().curPath();//保存当前所在的路径
    QListWidgetItem *pItem  =  m_pBookListW->currentItem();
    if(pItem == nullptr)
    {
        QMessageBox::warning(this,"删除文件","请选择要删除的文件");
    }
    else
    {
        QString strDelName = pItem->text();//获取文件的名字
        //路径长度较长的时候，cadata 的64个字节的长度不一定够，所以用camsg
        PDU *pdu = mkPDU(strCurPath.size()+1);
        pdu->uiMsgType = ENUM_MSG_TYPE_DEL_DIR_REQUEST;//删除路径请求
        strncpy(pdu->caData,strDelName.toStdString().c_str(),strDelName.size());//把要删除的文件名存入cadata
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);//传出pdu,长度为pdu的长度pdulen
        free(pdu);
        pdu = nullptr;
    }


}

void Book::renameFile()
{
    QString strCurPath = TcpClient::getInstance().curPath();//获取到当前的目录信息
    //获得要修改的文件名字
    QListWidgetItem *pItem  =  m_pBookListW->currentItem();
    if(pItem == nullptr)
    {
        QMessageBox::warning(this,"重命名文件","请选择要重命名的文件");
    }
    else
    {
        QString strOldName = pItem->text();
        QString strNewName = QInputDialog::getText(this,"重命名文件","请输入新的文件名");//输入对话框获得新名字
        if(!strNewName.isEmpty())
        {
            PDU *pdu = mkPDU(strCurPath.size() + 1);
            pdu->uiMsgType = ENUM_MSG_TYPE_RENAME_FILE_REQUEST;
            strncpy(pdu->caData,strOldName.toStdString().c_str(),strOldName.size());
            strncpy(pdu->caData+32,strNewName.toStdString().c_str(),strNewName.size());
            memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());//路径拷贝
            //发送给服务器
            TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);//传出pdu,长度为pdu的长度pdulen
            free(pdu);
            pdu = nullptr;
        }
        else
        {
            QMessageBox::warning(this,"重命名文件","新文件名不能为空");
        }
    }
}

void Book::enterDir(const QModelIndex &index)
{
    //双击进入文件夹
    QString strDirName = index.data().toString();
    m_strEnterDir = strDirName;
    QString strCurPath = TcpClient::getInstance().curPath();//当前所在的目录
    PDU *pdu = mkPDU(strCurPath.size() + 1);
    pdu->uiMsgType = ENUM_MSG_TYPE_ENTER_DIR_REQUEST;
    strncpy(pdu->caData,strDirName.toStdString().c_str(),strDirName.size());
    memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
    TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);//传出pdu,长度为pdu的长度pdulen
    free(pdu);
    pdu = nullptr;

}

void Book::uploadFile()
{
    //首先需要获取当前的路径

    //文件对话框
    m_strUploadFilePath = QFileDialog::getOpenFileName();//弹出文件窗口，string 是返回文件的路径
    qDebug() << m_strUploadFilePath;
    if(!m_strUploadFilePath.isEmpty())
    {
        int index = m_strUploadFilePath.lastIndexOf('/');//lastindexof 是从后往前找括号中的内容，返回的类型是int
        QString strFileName = m_strUploadFilePath.right(m_strUploadFilePath.size() - index - 1);//返回包含字符串最右边n个字符的子字符串。如果n大于或等于size（），或小于零，则返回整个字符串
        qDebug() <<strFileName;

        QFile file(m_strUploadFilePath);
        qint64 fileSize = file.size();//获得文件大小
        QString strCurPath =  TcpClient::getInstance().curPath();
        PDU *pdu = mkPDU(strCurPath.size() + 1);
        pdu->uiMsgType = ENUM_MSG_TYPE_UPLOAD_DIR_REQUEST;
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
        sprintf(pdu->caData,"%s %lld",strFileName.toStdString().c_str(),fileSize);
        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);//传出pdu,长度为pdu的长度pdulen
        free(pdu);
        pdu = nullptr;
        //请求后不要直接发送内容，容易发生沾包的情况，所以需要添加一个定时器,请求后不要直接发送内容
        m_pTimer->start(1000);//单位是毫秒,再发送请求之后的1000ms之后进行发送
    }
    else
    {
        QMessageBox::warning(this,"上传文件","上传文件名字不能为空");
    }

}

void Book::uploadFileData()
{
    //通过这个函数上传数据，也就是在uploadfile函数执行完成后进行
    m_pTimer->stop();//关闭计时器,不然会重新计时
    QFile file(m_strUploadFilePath);
    if(!file.open(QIODevice::ReadOnly))//上传失败
    {
        QMessageBox::warning(this,"打开文件","打开文件失败");
        return;
    }
    //上传成功
    char *pBuffer = new char[4096];//综合效率来看。4096最高
    qint64 ret = 0;
    while(true)//循环的从文件中读取数据
    {
        ret = file.read(pBuffer,4096);//读取数据到buffer，最大读到4096，不是表示每次都读到4096，实际读到的数据量是ret
        if(ret > 0 && ret <= 4096)//读到了数据
        {
            TcpClient::getInstance().getTcpSocket().write(pBuffer,ret);//pbuffer就是char*不用转换

        }
        else if(ret == 0)//读到文件末尾
        {
            break;
        }
        else//ret 小于0了
        {
            QMessageBox::warning(this,"上传文件","上传文件失败：读取文件失败");
            break;
        }
    }
    file.close();
    delete []pBuffer;
    pBuffer = nullptr;
}

void Book::delRegFile()
{
    //和删除目录一致，不过是请求的区别
    QString strCurPath = TcpClient::getInstance().curPath();//保存当前所在的路径
    QListWidgetItem *pItem  =  m_pBookListW->currentItem();
    if(pItem == nullptr)
    {
        QMessageBox::warning(this,"删除文件","请选择要删除的文件");
    }
    else
    {
        QString strDelName = pItem->text();//获取文件的名字
        //路径长度较长的时候，cadata 的64个字节的长度不一定够，所以用camsg
        PDU *pdu = mkPDU(strCurPath.size()+1);
        pdu->uiMsgType = ENUM_MSG_TYPE_DEL_FILE_REQUEST;//删除路径请求
        strncpy(pdu->caData,strDelName.toStdString().c_str(),strDelName.size());//把要删除的文件名存入cadata
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());
        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);//传出pdu,长度为pdu的长度pdulen
        free(pdu);
        pdu = nullptr;
    }
}

void Book::downloadFile()
{

    QListWidgetItem *pItem  =  m_pBookListW->currentItem();//当前所选的文件名字
    if(pItem == nullptr)
    {
        QMessageBox::warning(this,"下载文件","请选择要下载的文件");
    }
    else
    {
        QString strSaveFilePath = QFileDialog::getSaveFileName();//弹出窗口选择路径
        if(strSaveFilePath.isEmpty())
        {
            QMessageBox::warning(this,"现在文件","请指定保存的位置");
            m_strSaveFilePath.clear();
        }
        else
        {
            m_strSaveFilePath = strSaveFilePath;

        }
        QString strCurPath = TcpClient::getInstance().curPath();//保存当前所在的路径
        PDU *pdu = mkPDU(strCurPath.size() + 1);
        pdu->uiMsgType = ENUM_MSG_TYPE_DOWNLOAD_FILE_REQUEST;
        QString strFileName = pItem->text();
        strcpy(pdu->caData,strFileName.toStdString().c_str());//下载的文件名
        memcpy(pdu->caMsg,strCurPath.toStdString().c_str(),strCurPath.size());//所下载的文件目录
        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
    }
}

void Book::shareFile()
{
    //获得选择的文件
    QListWidgetItem *pItem  =  m_pBookListW->currentItem();//当前所选的文件名字
    if(pItem == nullptr)
    {
        QMessageBox::warning(this,"分享文件","请选择要分享的文件");
        return;
    }
    else
    {
        //获得要分享的文件名字
        m_strShareFileName = pItem->text();

    }
    Friend *pFriend = OpeWidget::getInstance().getFriend();//获得好友界面
    QListWidget *pFriendList = pFriend->getFriendList();
    ShareFile::getinstance().updateFriend(pFriendList);
    if(ShareFile::getinstance().isHidden())
    {
        ShareFile::getinstance().show();
    }

}

void Book::moveFile()
{
    QListWidgetItem *pCurItem =  m_pBookListW->currentItem();
    if(nullptr != pCurItem)//表示选择了这个文件
    {
        m_strMoveFileName =  pCurItem->text();
        QString strCurPath =  TcpClient::getInstance().curPath();
        m_strMoveFilePath = strCurPath +"/" + m_strMoveFileName;//文件名字拼接
        m_pSelectDirPB->setEnabled(true);

    }
    else
    {
        QMessageBox::warning(this,"移动文件","请选择要移动的文件");
    }

}

void Book::selectDestDir()
{
    QListWidgetItem *pCurItem =  m_pBookListW->currentItem();
    if(nullptr != pCurItem)//表示选择了这个文件
    {
        QString strDestDir =  pCurItem->text();
        QString strCurPath =  TcpClient::getInstance().curPath();
        m_strDestDir = strCurPath +"/" + strDestDir;//文件名字拼接

        int srcLen = m_strMoveFilePath.size();
        int destLen = m_strDestDir.size();
        PDU *pdu = mkPDU(srcLen + destLen + 2);//每一个路径后面都有一个\0；
        pdu->uiMsgType = ENUM_MSG_TYPE_MOVE_FILE_REQUEST;
        sprintf(pdu->caData,"%d %d %s",srcLen,destLen,m_strMoveFileName.toStdString().c_str());//文件名字放入cadata
        //文件路径放到camsg

        memcpy(pdu->caMsg,m_strMoveFilePath.toStdString().c_str(),srcLen);
        memcpy((char*)(pdu->caMsg) + (srcLen + 1) , m_strDestDir.toStdString().c_str(),destLen);

        TcpClient::getInstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu = nullptr;




    }
    else
    {
        QMessageBox::warning(this,"移动文件","请选择要移动的文件");
    }
    m_pSelectDirPB->setEnabled(false);//选择了之后设置为false
}


